﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using PaperRenderingInterfaces;
using RenderEngineInterfaces;
using HtmlAgilityPack;
using PaperPluginUtilities;
using DeepZoomPivotConstructor.PivotLib;
using DeepZoomPivotConstructor.VisualLib;

namespace HTMLTablePageScanner
{
    /// <summary>
    /// Scan a table for images. Instead of expecting things to be
    /// on every single row, it expects all the info to be contained in
    /// a single cell - for the whole web page.
    /// </summary>
    [Export(typeof(IPaperRender))]
    [PaperRender("HTMLSimpleTableCells")]
    public class WebTableCellScanner : IPaperRender
    {
        /// <summary>
        /// Fetch info from the web
        /// </summary>
        [Import]
        IWebAccess WebGetter;

        /// <summary>
        /// Render to visuals whatever it is we are looking at
        /// </summary>
        [Import]
        IRenderEngine MyRender;

        /// <summary>
        /// Scan the web page that is given!
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        public IEnumerable<DeepZoomPivotConstructor.PivotLib.PivotImage> Render(string renderAddress)
        {
            Uri baseUri = new Uri(renderAddress);
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(WebGetter.GetUriAsString(baseUri));

            ///
            /// Get all the URL links we can, along with whatever text we need
            /// 

           
            var allCells = new EnumerableWrapper<HtmlNode>(doc.DocumentNode.SelectNodes("//td"));
            var allImageUrls = from c in new EnumerableWrapper<HtmlNode>(doc.DocumentNode.SelectNodes("//td"))
                               from i in FindImagesInCell(c, baseUri)
                               select i;

            ///
            /// Now, because of the way we scan this stuff, some of these guys might end up duplicates, so remove them
            /// 

            var uniqueImageUrls = allImageUrls.Distinct(new CompareImageURL());

            ///
            /// Next, some of the links will be refering to the same file, just different types (gif, eps, etc.).
            /// 

            var groupedImages = from l in uniqueImageUrls
                                where ImageUrlParsing.IsPictureType(l.url)
                                group l by ImageUrlParsing.GetPictureFileName(l.url);

            ///
            /// Next, craete the basic PivotImage with all the required info around it.
            /// 

            var images = groupedImages.Select(ls =>
            {
                var info = ImageUrlParsing.GetBestImage(ls);
                Visual v = MyRender.Render(new Uri(baseUri, info.url), forceAsComposableUnit: true);
                PivotImage p = new PivotImage(v);
                p.Name = info.urlName;

                ls.Execute(l => p.Add("Graphics Files", ImageUrlParsing.GetNormalizedFileExtension(l.url), new Uri(baseUri, l.url)));

                DateTime? whenModified = WebGetter.GetLastModificationTime(new Uri(baseUri, info.url));
                if (whenModified.HasValue)
                {
                    p.Add("Date", whenModified.Value);
                }
                else
                {
                    p.Add("Date", DateTime.Now);
                }

                p.Add("Caption", "<none specified>");
                p.Add("More Information", "Note Web Page", baseUri);

                return p;
            });

            return images;
        }

        /// <summary>
        /// Quck way to compare two images!
        /// </summary>
        class CompareImageURL : IEqualityComparer<ImageUrlParsing.LinkInfo>
        {
            public bool Equals(ImageUrlParsing.LinkInfo x, ImageUrlParsing.LinkInfo y)
            {
                return x.url == y.url;
            }

            public int GetHashCode(ImageUrlParsing.LinkInfo obj)
            {
                return obj.url.GetHashCode();
            }
        }


        /// <summary>
        /// Find all the images in a particular cell.
        /// </summary>
        /// <param name="cellHtml"></param>
        /// <returns></returns>
        private IEnumerable<ImageUrlParsing.LinkInfo> FindImagesInCell(HtmlNode cellHtml, Uri baseUri)
        {
            var result = cellHtml.ScanSubNodes("a").Where(l => l.Attributes["href"] != null).Select(linkNode =>
            {
                ImageUrlParsing.LinkInfo info;
                info.url = linkNode.Attributes["href"].Value;
                info.urlName = linkNode.InnerText.CleanHTMLText();
                if (info.urlName == null || info.urlName.Length == 0)
                {
                    info.urlName = ImageUrlParsing.GetPictureFileName(info.url);
                }
                return info;
            });

            return result;
        }
    }
}
